import QtQuick 1.0
import Box2D 1.0

Item {
    id: bike

    property int centerX: rearWheel.x / 2 + wheel.x / 2 - screen.width / 8
    property int centerY: (human.y - human.height) / 2
                          + (wheel.y + wheel.height) / 2
                          + screen.height / 3

    property alias bikeBodyX: bikeBody.x
    property alias bikeBodyY: bikeBody.y
    property alias bikeRotation: bikeBody.rotation
    property alias wheelX: wheel.x
    property alias wheelY: wheel.y
    property alias wheelRot: wheel.rotation
    property alias rearWheelX: rearWheel.x
    property alias rearWheelY: rearWheel.y
    property alias rearWheelRot: rearWheel.rotation
    property alias humanX: human.x
    property alias humanY: human.y
    property alias humanRot: human.rotation
    property alias headX: head.x
    property alias headY: head.y
    property alias headRot: head.rotation
    property alias armX: arm.x
    property alias armY: arm.y
    property alias armRot: arm.rotation
    property alias handX: hand.x
    property alias handY: hand.y
    property alias handRot: hand.rotation
    property alias rearForkX: rearFork.x
    property alias rearForkY: rearFork.y
    property alias rearForkRot: rearFork.rotation
    property alias suspLowerX: suspLower.x
    property alias suspLowerY: suspLower.y
    property alias suspLowerRot: suspLower.rotation
    property alias motorSpeed: rearWheel.angularVelocity

    function accelerate(speed)
    {
        frontWheelToFork.enableMotor = false;
        motor.enableMotor = true;
        motor.motorSpeed = speed;
    }

    function rearBrake()
    {
        motor.enableMotor = true;
        motor.motorSpeed = 0;
    }

    function frontBrake()
    {
        frontWheelToFork.enableMotor = true;
        frontWheelToFork.motorSpeed = 0;
    }
    function leanForward()
    {
        human.applyTorque(-5);

        if (bikeBody.angularVelocity > -Math.PI / 2)
            bikeBody.applyTorque(-25);
    }

    function leanBackward()
    {
        human.applyTorque(5);

        if (bikeBody.angularVelocity < Math.PI / 2)
            bikeBody.applyTorque(25);
    }

    function freeRearWheel()
    {
        motor.enableMotor = false;
    }

    function freeFrontWheel()
    {
        frontWheelToFork.enableMotor = false;
    }

    function setAtStart()
    {
        console.debug("Bike.qml: setAtStart(): Screen size is",
                      screen.width, "x", screen.height);

        world.resetVelocities();
        bikeBodyX = 355 / 1500 * screen.width - x
        bikeBodyY = 1270 / 844 * screen.height - y
        bikeRotation = 27
        wheelX = 612 / 1500 * screen.width - x
        wheelY = 1662 / 844 * screen.height - y
        rearWheelX = 304 / 1500 * screen.width - x
        rearWheelY = 1495 / 844 * screen.height - y
        humanX = 460 / 1500 * screen.width - x
        humanY = 1280 / 844 * screen.height - y
        humanRot = 0
        headX = 480 / 1500 * screen.width - x
        headY = 1280 / 844 * screen.height - y - height
        headRot = 20
        armX = 480 / 1500 * screen.width - x
        armY = 1280 / 844 * screen.height - y
        armRot = 45
        handX = 550 / 1500 * screen.width - x
        handY = 1345 / 844 * screen.height - y
        handRot = 45

        if (humanToBike.released)
            humanToBike.grab();

        if (handToBike.released)
            handToBike.grab();

        if (armToBike.released)
            armToBike.grab();

        rearForkX = 300 / 1500 * screen.width - x
        rearForkY = 1482 / 844 * screen.height - y
        rearForkRot = 10
        suspLowerX = 597 / 1500 * screen.width - x
        suspLowerY = 1620 / 844 * screen.height - y
        suspLowerRot = 0
    }

    width: bikeBody.bikeWidth + wheel.wheelWidth
    height: bikeBody.bikeHeight + wheel.wheelHeight

    Body {
        id: wheel

        property alias wheelWidth: wheelImage.width
        property alias wheelHeight: wheelImage.height

        parent: bike.parent
        fixedRotation: false
        sleepingAllowed: false
        x: 612 / 1500 * screen.width - bike.x
        y: 1662 / 844 * screen.height - bike.y
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        fixtures: Circle {
            radius: 80 / 1500 * screen.width
            density: 0.1
            friction: 0.9
            restitution: 0.2
        }

        Image {
            id: wheelImage
            anchors.centerIn: parent
            source: "gfx/wheel.png"
            width: 160 / 1500 * screen.width
            height: width
            smooth: true
        }
    }
    Body {
        id: rearWheel

        parent: bike.parent
        fixedRotation: false
        sleepingAllowed: false
        x: 304 / 1500 * screen.width - bike.x
        y: 1495 / 844 * screen.height - bike.y
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        onAngularVelocityChanged: {
            var speed = -angularVelocity / 30 + 0.5;
            if (speed > 0.5)
                speedChanged(speed);
            else
                speedChanged(0.5);
        }

        fixtures: Circle {
            radius: 75 / 1500 * screen.width
            density: 0.4
            friction: 1.0
            restitution: 0.2
        }

        Image {
            anchors.centerIn: parent
            source: "gfx/rearWheel.png"
            width: 150 / 1500 * screen.width
            height: width
            smooth: true
        }
    }

    Body {
        id: rearFork

        parent: bike.parent
        fixedRotation: false
        sleepingAllowed: false
        x: 300 / 1500 * screen.width - bike.x
        y: 1482 / 844 * screen.height - bike.y
        width: 150 / 1500 * screen.width
        height: 40 / 844 * screen.height
        rotation: 10
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        fixtures: Box {
            anchors.fill: parent
            density: 0.5
            friction: 1;
            restitution: 0.2
        }

        Image {
            source: "gfx/rearFork.png"
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            width: parent.width
            height: parent.height * 2
        }
    }

    Body {
        id: suspLower

        parent: bike.parent
        fixedRotation: false
        sleepingAllowed: false
        x: 597 / 1500 * screen.width - bike.x
        y: 1620 / 844 * screen.height - bike.y
        width: 20 / 1500 * screen.width
        height: 50 / 844 * screen.height
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        fixtures: Box {
            anchors.fill: parent
            density: 0.8
            friction: 1;
            restitution: 0.2
        }

        Image {
            source: "gfx/susp_lower_long.png"
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            width: parent.width
            height: parent.height * 4
        }
    }

    Body {
        id: bikeBody

        property real size: 1.5 / 1500 * screen.width
        property alias bikeWidth: bikeImage.width
        property alias bikeHeight: bikeImage.height

        parent: bike.parent
        sleepingAllowed: false
        x: 355 / 1500 * screen.width - bike.x
        y: 1270 / 844 * screen.height - bike.y
        rotation: 27
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        fixtures: [ Polygon {
                density: 0.5
                friction: 1.0
                restitution: 0.2
                vertices: [
                    Qt.point(0, 35 * bikeBody.size),
                    Qt.point(50 * bikeBody.size, 50 * bikeBody.size),
                    Qt.point(50 * bikeBody.size, 40 * bikeBody.size)
                ]
            },
            Polygon {
                density: 0.5
                friction: 1.0
                restitution: 0.2
                vertices: [
                    Qt.point(50 * bikeBody.size, 40 * bikeBody.size),
                    Qt.point(50 * bikeBody.size, 50 * bikeBody.size),
                    Qt.point(90 * bikeBody.size, 100 * bikeBody.size),
                    Qt.point(120 * bikeBody.size, 100 * bikeBody.size),
                    Qt.point(120 * bikeBody.size, 45 * bikeBody.size)
                ]
            },
            Polygon {
                density: 0.5
                friction: 1.0
                restitution: 0.2
                vertices: [
                    Qt.point(120 * bikeBody.size, 45 * bikeBody.size),
                    Qt.point(120 * bikeBody.size, 140 * bikeBody.size),
                    Qt.point(180 * bikeBody.size, 140 * bikeBody.size),
                    Qt.point(180 * bikeBody.size, 35 * bikeBody.size)
                ]
            },
            Polygon {
                id: bikeFix
                density: 0.5
                friction: 1.0
                restitution: 0.2
                vertices: [
                    Qt.point(180 * bikeBody.size, 0),
                    Qt.point(180 * bikeBody.size, 135 * bikeBody.size),
                    Qt.point(230 * bikeBody.size, 60 * bikeBody.size),
                    Qt.point(210 * bikeBody.size, 0)
                ]
            }
        ]

        Image {
            id: bikeImage
            width: 300 * parent.size
            height: sourceSize.height / sourceSize.width * width
            source: "gfx/bikeBody.png"
        }
    }

    DistanceJoint {
        id: joint2
        parent: bike.parent
        frequencyHz: 5
        dampingRatio: 0.1
        collideConnected: true
        bodyA: bikeBody
        bodyB: suspLower
    }

    PrismaticJoint {
        id: prismatic
        parent: bike.parent
        lowerTranslation: -1
        upperTranslation: 1
        enableLimit: true
        collideConnected: true
        bodyA: bikeBody
        bodyB: suspLower
        axis: Qt.point(0, 1)
    }

    RevoluteJoint {
        id: frontWheelToFork
        parent: bike.parent
        maxMotorTorque: 300
        motorSpeed: 0
        bodyA: wheel
        bodyB: suspLower
    }

    RevoluteJoint {
        id: motor
        parent: bike.parent
        maxMotorTorque: 2
        motorSpeed: 0
        bodyA: rearWheel
        bodyB: rearFork
    }

    RevoluteJoint {
        id: rearForkToBody
        parent: bike.parent
        maxMotorTorque: 300
        motorSpeed: 0
        bodyA: rearFork
        bodyB: bikeBody
        localAnchorA: Qt.point(rearFork.width, rearFork.height / 2)
    }

    DistanceJoint {
        id: rearSuspension
        parent: bike.parent
        frequencyHz: 5
        dampingRatio: 0.1
        collideConnected: true
        bodyA: bikeBody
        bodyB: rearFork
        localAnchorA: Qt.point(0, 0)
        localAnchorB: Qt.point(0, 0)
    }

    Body {
        id: head

        parent: bike.parent
        x: 480 / 1500 * screen.width - bike.x
        y: 1280 / 844 * screen.height - bike.y - height
        width: 90 / 1500 * screen.width
        height: 70 / 844 * screen.height
        rotation: 20

        fixtures: Box {
            anchors.fill: parent
            friction: 1.0
            density: 0.1
            restitution: 0.2
            onBeginContact: {
                if (other != armFix && other != bikeFix) {
                    humanToBike.release();
                    handToBike.release();
                    armToBike.release();

                    if (!dead)
                        die();
                }
            }
        }
    }

    Body {
        id: human

        parent: bike.parent
        x: 460 / 1500 * screen.width - bike.x
        y: 1280 / 844 * screen.height - bike.y
        width: 40 / 1500 * screen.width
        height: 150 / 844 * screen.height
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        fixtures: Box {
            anchors.fill: parent
            friction: 1.0
            density: 0.1
            restitution: 0.2
        }

        Image {
            anchors.right: parent.right
            width: parent.width * 3
            height: parent.height * 1.8
            source: "gfx/human.png"
        }

        Image {
            width: sourceSize.width * screen.width / 640
            height: sourceSize.height * screen.height / 360
            y: -height * 0.7
            rotation: 20
            source: "gfx/head.png"
        }
    }

    Body {
        id: hand

        parent: bike.parent
        x: 550 / 1500 * screen.width - bike.x
        y: 1345 / 844 * screen.height - bike.y
        width: 80 / 1500 * screen.width
        height: 20 / 844 * screen.height
        rotation: 45
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic

        fixtures: Box {
            anchors.fill: parent
            friction: 1.0
            density: 0.1
            restitution: 0.2
        }

        Image {
            rotation: -5
            anchors.centerIn: parent
            width: parent.width * 1.2
            height: parent.height * 1.4
            source: "gfx/hand.png"
        }
    }

    Body {
        id: arm

        parent: bike.parent
        x: 480 / 1500 * screen.width - bike.x
        y: 1280 / 844 * screen.height - bike.y
        width: 100 / 1500 * screen.width
        height: 20 / 844 * screen.height
        rotation: 45
        bodyType: world.staticWorld ? Body.Static : Body.Dynamic


        fixtures: Box {
            id: armFix
            anchors.fill: parent
            friction: 1.0
            density: 0.1
            restitution: 0.2
        }

        Image {
            rotation: -10
            y: -10
            width: parent.width * 1.1
            height: parent.height * 2.5
            source: "gfx/arm.png"
        }
    }

    WeldJoint {
        id: headWeld
        parent: bike.parent
        bodyA: head
        bodyB: human
    }

    RevoluteJoint {
        id: humanToBike

        parent: bike.parent
        maxMotorTorque: 300
        motorSpeed: 0
        bodyA: human
        bodyB: bikeBody
        localAnchorA: Qt.point(human.width / 2, human.height)
    }

    RevoluteJoint {
        id: humanToArm
        parent: bike.parent
        maxMotorTorque: 300
        motorSpeed: 0
        bodyA: human
        bodyB: arm
        localAnchorA: Qt.point(human.width / 2, 0)
    }

    RevoluteJoint {
        id: armToHand
        parent: bike.parent
        maxMotorTorque: 300
        motorSpeed: 0
        bodyA: arm
        bodyB: hand
        localAnchorA: Qt.point(arm.width-30 / 1500 * screen.width,
                               arm.width-20 / 900 * screen.height)
    }

    RevoluteJoint {
        id: handToBike

        parent: bike.parent
        maxMotorTorque: 300
        motorSpeed: 0
        bodyA: hand
        bodyB: bikeBody
        localAnchorA: Qt.point(hand.width-30 / 1500 * screen.width,
                               hand.width-20 / 900 * screen.height)
    }

    DistanceJoint {
        id: armToBike

        parent: bike.parent
        frequencyHz: 10
        dampingRatio: 1.0
        length: 10
        collideConnected: true
        bodyA: hand
        bodyB: bikeBody
        localAnchorA: Qt.point(hand.width, 0)
        localAnchorB: Qt.point(bikeBody.bikeWidth / 2, 0)
    }
}
